`ifndef LILYRISCV_V
`define LILYRISCV_V


`include "defines.v"

module LilyRiscv(
	input  wire 		  clk   		,
	input  wire 		  rstn		    , 

    // from rom
    output [`InstAddrWidth - 1 : 0] inst_addr_o   ,
	input  [`InstWidth - 1 : 0]     inst_i		
);

//pc to if
wire[`InstAddrWidth - 1 : 0]    pc_reg_pc_o;

//instf to instf_id
wire[`InstAddrWidth - 1 : 0]    instf_inst_addr_o;
wire[`InstWidth - 1 : 0]        instf_inst_o;	

// instf_id to id
wire[`InstAddrWidth - 1 : 0]    instf_id_inst_addr_o;
wire[`InstWidth - 1 : 0]        instf_id_inst_o;	

//id to regs
wire[`RegAddrWidth - 1 : 0]     id_reg1_raddr_o;
wire[`RegAddrWidth - 1 : 0]     id_reg2_raddr_o;

//id to id_ex
wire[`InstAddrWidth - 1 : 0]    id_inst_addr_o;
wire[`InstWidth - 1 : 0]        id_inst_o;
wire[`RegAddrWidth - 1 : 0]     id_reg_waddr_o;
wire                            id_reg_wen_o;
wire[`RegDataWidth - 1 : 0]     id_reg1_rdata_o;
wire[`RegDataWidth - 1 : 0]     id_reg2_rdata_o;
wire[`OPWidth - 1 : 0]          id_op1_o;
wire[`OPWidth - 1 : 0]          id_op2_o;

//regs to id
wire[`RegDataWidth - 1 : 0]     regs_reg1_rdata_o;
wire[`RegDataWidth - 1 : 0]     regs_reg2_rdata_o;

//id_ex to ex
wire[`InstAddrWidth - 1 : 0]    id_ex_inst_addr_o;
wire[`InstWidth - 1 : 0]        id_ex_inst_o;
wire[`RegAddrWidth - 1 : 0]     id_ex_reg_waddr_o;
wire                            id_ex_reg_wen_o;
wire[`RegDataWidth - 1 : 0]     id_ex_reg1_rdata_o;
wire[`RegDataWidth - 1 : 0]     id_ex_reg2_rdata_o;
wire[`OPWidth - 1 : 0]          id_ex_op1_o;
wire[`OPWidth - 1 : 0]          id_ex_op2_o;

//ex to regs
wire[`RegAddrWidth - 1 : 0]     ex_waddr_o;
wire[`RegDataWidth - 1 : 0]     ex_wdata_o;
wire                            ex_wen_o;

pc_reg u_pc_reg(
    .clk			(clk        ),
    .rstn			(rstn       ),	
    .pc_o   		(pc_reg_pc_o)
);

instf u_instf(
    .pc_i		        (pc_reg_pc_o        ),
    .instf2rom_addr_o	(inst_addr_o        ), 
    .rom_inst_i		    (inst_i             ),
    .inst_addr_o	    (instf_inst_addr_o  ), 
    .inst_o             (instf_inst_o       )
);

instf_id u_instf_id(
    .clk			(clk		            ),
    .rstn			(rstn		            ),
    .inst_addr_i	(instf_inst_addr_o      ),
    .inst_i			(instf_inst_o           ),    
    .inst_addr_o	(instf_id_inst_addr_o   ), 
    .inst_o         (instf_id_inst_o	    )
);

id u_id(
    .inst_addr_i	(instf_id_inst_addr_o	),
    .inst_i			(instf_id_inst_o		),
    .reg1_raddr_o   (id_reg1_raddr_o		),
    .reg2_raddr_o	(id_reg2_raddr_o		),
    .reg1_rdata_i	(regs_reg1_rdata_o      ),
    .reg2_rdata_i	(regs_reg2_rdata_o      ),
    .inst_addr_o	(id_inst_addr_o		    ),	
    .inst_o			(id_inst_o			    ),
    .reg_waddr_o	(id_reg_waddr_o		    ),	
    .reg_wen_o      (id_reg_wen_o			),
    .reg1_rdata_o	(id_reg1_rdata_o		),
    .reg2_rdata_o	(id_reg2_rdata_o	    ),
    .op1_o			(id_op1_o			    ),	
    .op2_o			(id_op2_o			    )
);

regs u_regs(
    .clk			(clk				),
    .rstn			(rstn				),
    .reg1_raddr_i	(id_reg1_raddr_o	),
    .reg2_raddr_i	(id_reg2_raddr_o	), 
    .reg1_rdata_o	(regs_reg1_rdata_o	),
    .reg2_rdata_o	(regs_reg2_rdata_o	),
    .waddr_i	    (ex_waddr_o			),
    .wdata_i	    (ex_wdata_o			),
    .wen_i          (ex_wen_o			)
);

id_ex u_id_ex(
    .clk			(clk					),
    .rstn			(rstn					),
    .inst_addr_i	(id_inst_addr_o			),
    .inst_i			(id_inst_o				),
    .reg_waddr_i	(id_reg_waddr_o			),
    .reg_wen_i		(id_reg_wen_o			),
    .reg1_rdata_i   (id_reg1_rdata_o        ),
    .reg2_rdata_i	(id_reg2_rdata_o	    ),
    .op1_i			(id_op1_o				),
    .op2_i			(id_op2_o				),
    .inst_addr_o    (id_ex_inst_addr_o		),
    .inst_o			(id_ex_inst_o			),
    .reg_waddr_o	(id_ex_reg_waddr_o	    ),
    .reg_wen_o		(id_ex_reg_wen_o		),
    .reg1_rdata_o   (id_ex_reg1_rdata_o     ),
    .reg2_rdata_o   (id_ex_reg2_rdata_o     ),
    .op1_o			(id_ex_op1_o			),
    .op2_o			(id_ex_op2_o			)	
);

ex ex_inst(
    .inst_addr_i	(id_ex_inst_addr_o	),
    .inst_i			(id_ex_inst_o		),	
    .reg_waddr_i	(id_ex_reg_waddr_o	),
    .reg_wen_i		(id_ex_reg_wen_o	),
    .reg1_rdata_i   (id_ex_reg1_rdata_o ),
    .reg2_rdata_i   (id_ex_reg2_rdata_o ),
    .op1_i			(id_ex_op1_o		),
    .op2_i			(id_ex_op2_o		),	
    .waddr_o		(ex_waddr_o			),
    .wdata_o		(ex_wdata_o			),	
    .wen_o          (ex_wen_o			)	
);

endmodule

`endif // LILYRISCV_V